﻿using System;
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
using NetTopologySuite.Mathematics;

namespace NetTopologySuite.Shape.Random
{
	public class RandomPointsInGridBuilder : GeometricShapeBuilder
	{
		public RandomPointsInGridBuilder() : this(new GeometryFactory())
		{
		}

		public RandomPointsInGridBuilder(IGeometryFactory geomFact) : base(geomFact)
		{
		}

		public bool ConstrainedToCircle
		{
			get
			{
				return this._isConstrainedToCircle;
			}
			set
			{
				this._isConstrainedToCircle = value;
			}
		}

		public double GutterFraction { get; set; }

		public override IGeometry GetGeometry()
		{
			int num = (int)System.Math.Sqrt((double)base.NumPoints) + 1;
			if (num * num < base.NumPoints)
			{
				num++;
			}
			double num2 = base.Extent.Width / (double)num;
			double num3 = base.Extent.Height / (double)num;
			double num4 = MathUtil.Clamp(this.GutterFraction, 0.0, 1.0);
			double num5 = num2 * num4 / 2.0;
			double num6 = num3 * num4 / 2.0;
			double num7 = 1.0 - num4;
			double xLen = num7 * num2;
			double yLen = num7 * num3;
			Coordinate[] array = new Coordinate[num * num];
			int num8 = 0;
			for (int i = 0; i < num; i++)
			{
				for (int j = 0; j < num; j++)
				{
					double orgX = base.Extent.MinX + (double)i * num2 + num5;
					double orgY = base.Extent.MinY + (double)j * num3 + num6;
					array[num8++] = this.RandomPointInCell(orgX, orgY, xLen, yLen);
				}
			}
			return this.GeomFactory.CreateMultiPoint(array);
		}

		private Coordinate RandomPointInCell(double orgX, double orgY, double xLen, double yLen)
		{
			if (!this._isConstrainedToCircle)
			{
				return this.RandomPointInGridCell(orgX, orgY, xLen, yLen);
			}
			return RandomPointsInGridBuilder.RandomPointInCircle(orgX, orgY, xLen, yLen);
		}

		private Coordinate RandomPointInGridCell(double orgX, double orgY, double xLen, double yLen)
		{
			double x = orgX + xLen * RandomPointsInGridBuilder.Rnd.NextDouble();
			double y = orgY + yLen * RandomPointsInGridBuilder.Rnd.NextDouble();
			return base.CreateCoord(x, y);
		}

		private static Coordinate RandomPointInCircle(double orgX, double orgY, double width, double height)
		{
			double num = orgX + width / 2.0;
			double num2 = orgY + height / 2.0;
			double num3 = System.Math.PI*2 * RandomPointsInGridBuilder.Rnd.NextDouble();
			double num4 = System.Math.Sqrt(RandomPointsInGridBuilder.Rnd.NextDouble());
			double num5 = width / 2.0 * num4 * Math.Cos(num3);
			double num6 = height / 2.0 * num4 * Math.Sin(num3);
			double x = num + num5;
			double y = num2 + num6;
			return new Coordinate(x, y);
		}

        protected static readonly System.Random Rnd = new System.Random();

		private bool _isConstrainedToCircle;
	}
}
